improvement(copilot): edit old messages, aborts, reverts, model selection, context window#1675
Merged
improvement(copilot): edit old messages, aborts, reverts, model selection, context window#1675
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
💡 Enable Vercel Agent with $100 free credit for automated AI reviews |
Contributor
There was a problem hiding this comment.
Greptile Overview
Summary
This PR implements significant Copilot UI improvements including message editing, checkpoint reverts, model selection, and context window tracking.
Key Changes:
- Message Editing: Users can click on their messages to edit them inline, which truncates the conversation and resends from that point
- Checkpoint Management: Added UI to revert to previous workflow states with confirmation modals
- Context Usage Tracking: New endpoint to fetch and display token usage from sim-agent API
- Model Selection: Enhanced model switching with
claude-4.5-haikusupport and user preference loading - Chat Management: Added delete and rename functionality for chat history
- Abort Functionality: Users can abort in-progress message generation
- UI Polish: Improved message dimming during edits/reverts, better spacing, and inline confirmation modals
Architecture:
- New API endpoints:
/api/copilot/context-usageand/api/copilot/chat/delete - Billing API simplified to accept pre-calculated costs
- Chat API now sends single messages instead of full history to sim-agent
- Enhanced blocks metadata tool with cleaner output format
Confidence Score: 2/5
- Critical authorization vulnerability in chat deletion allows any authenticated user to delete any chat
- The delete endpoint (
apps/sim/app/api/copilot/chat/delete/route.ts:25) lacks ownership verification, allowing users to delete other users' chats. Additionally, the context usage endpoint logs API keys. While the feature implementation is comprehensive and well-structured, these security issues need immediate attention. - Critical:
apps/sim/app/api/copilot/chat/delete/route.ts(missing authorization check). Attention needed:apps/sim/app/api/copilot/context-usage/route.ts(API key logging)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| apps/sim/app/api/copilot/chat/delete/route.ts | 2/5 | New delete endpoint missing authorization check - any user can delete any chat |
| apps/sim/app/api/copilot/context-usage/route.ts | 3/5 | New context usage endpoint with API key potentially logged in headers |
| apps/sim/stores/copilot/store.ts | 4/5 | Major refactor adding message editing, context usage tracking, and checkpoint management |
| apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/copilot-message.tsx | 4/5 | Added message editing, checkpoint revert UI, and abort functionality with inline UserInput |
| apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/user-input.tsx | 4/5 | Enhanced with portal-based mention menu, clearOnSubmit prop, and improved positioning |
Sequence Diagram
sequenceDiagram
participant User
participant CopilotUI as Copilot UI
participant UserMessage as User Message
participant Store as Copilot Store
participant ChatAPI as Chat API
participant ContextAPI as Context Usage API
participant SimAgent as Sim Agent
Note over User,SimAgent: Message Edit Flow
User->>UserMessage: Click on message
UserMessage->>UserMessage: Enter edit mode
UserMessage->>CopilotUI: onEditModeChange(true)
CopilotUI->>CopilotUI: Dim messages after edited one
User->>UserMessage: Edit message & submit
UserMessage->>Store: sendMessage(edited, {messageId})
Store->>Store: Truncate messages after edited
Store->>ChatAPI: POST /api/copilot/chat
ChatAPI->>SimAgent: Forward request with message
SimAgent-->>ChatAPI: SSE stream response
ChatAPI-->>Store: Stream events
Store->>Store: Update streaming message
Store->>CopilotUI: Update messages
Store->>ContextAPI: fetchContextUsage()
ContextAPI->>SimAgent: POST /api/get-context-usage
SimAgent-->>ContextAPI: Token usage data
ContextAPI-->>Store: Context usage updated
Note over User,SimAgent: Checkpoint Revert Flow
User->>UserMessage: Click revert button
UserMessage->>UserMessage: Show confirmation modal
UserMessage->>CopilotUI: onRevertModeChange(true)
CopilotUI->>CopilotUI: Dim messages after checkpoint
User->>UserMessage: Confirm revert
UserMessage->>Store: revertToCheckpoint(checkpointId)
Store->>ChatAPI: POST /api/copilot/checkpoints/revert
ChatAPI-->>Store: Workflow state restored
Store->>Store: Remove used checkpoint
Store->>Store: Truncate messages after checkpoint
UserMessage->>UserMessage: Enter edit mode
UserMessage->>CopilotUI: onEditModeChange(true)
Note over User,SimAgent: Chat Deletion Flow
User->>CopilotUI: Click delete in history
CopilotUI->>Store: deleteChat(chatId)
Store->>ChatAPI: DELETE /api/copilot/chat/delete
ChatAPI->>ChatAPI: Delete without ownership check
ChatAPI-->>Store: Success
Store->>Store: Remove from local state
CopilotUI->>CopilotUI: Update UI
Note over User,SimAgent: Model Selection Flow
User->>CopilotUI: Change selected model
CopilotUI->>Store: setSelectedModel(model)
Store->>ContextAPI: fetchContextUsage()
ContextAPI->>SimAgent: POST with new model
SimAgent-->>ContextAPI: Updated context usage
ContextAPI-->>Store: Updated percentage
Store->>CopilotUI: Update context pill display
24 files reviewed, 3 comments
Comment on lines
+25
to
+26
| // Delete the chat | ||
| await db.delete(copilotChats).where(eq(copilotChats.id, parsed.chatId)) |
Contributor
There was a problem hiding this comment.
logic: Delete without verifying ownership - any authenticated user can delete any chat
Suggested change
| // Delete the chat | |
| await db.delete(copilotChats).where(eq(copilotChats.id, parsed.chatId)) | |
| // Verify chat ownership | |
| const chat = await db.select().from(copilotChats).where(eq(copilotChats.id, parsed.chatId)).limit(1) | |
| if (chat.length === 0 || chat[0].userId !== session.user.id) { | |
| return NextResponse.json({ success: false, error: 'Chat not found or unauthorized' }, { status: 404 }) | |
| } | |
| // Delete the chat | |
| await db.delete(copilotChats).where(eq(copilotChats.id, parsed.chatId)) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/api/copilot/chat/delete/route.ts
Line: 25:26
Comment:
**logic:** Delete without verifying ownership - any authenticated user can delete any chat
```suggestion
// Verify chat ownership
const chat = await db.select().from(copilotChats).where(eq(copilotChats.id, parsed.chatId)).limit(1)
if (chat.length === 0 || chat[0].userId !== session.user.id) {
return NextResponse.json({ success: false, error: 'Chat not found or unauthorized' }, { status: 404 })
}
// Delete the chat
await db.delete(copilotChats).where(eq(copilotChats.id, parsed.chatId))
```
How can I resolve this? If you propose a fix, please make it concise.
Comment on lines
+95
to
+97
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| ...(env.COPILOT_API_KEY ? { 'x-api-key': env.COPILOT_API_KEY } : {}), |
Contributor
There was a problem hiding this comment.
logic: API key exposed in logs when logging request headers
Suggested change
| headers: { | |
| 'Content-Type': 'application/json', | |
| ...(env.COPILOT_API_KEY ? { 'x-api-key': env.COPILOT_API_KEY } : {}), | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| ...(env.COPILOT_API_KEY ? { 'x-api-key': '[REDACTED]' } : {}), | |
| }, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/api/copilot/context-usage/route.ts
Line: 95:97
Comment:
**logic:** API key exposed in logs when logging request headers
```suggestion
headers: {
'Content-Type': 'application/json',
...(env.COPILOT_API_KEY ? { 'x-api-key': '[REDACTED]' } : {}),
},
```
How can I resolve this? If you propose a fix, please make it concise.
Comment on lines
+1609
to
+1613
| // If messageId is provided, check if it already exists (e.g., from edit flow) | ||
| const existingIndex = messageId ? currentMessages.findIndex((m) => m.id === messageId) : -1 | ||
| if (existingIndex !== -1) { | ||
| // Replace existing message instead of adding new one | ||
| newMessages = [...currentMessages.slice(0, existingIndex), userMessage, streamingMessage] |
Contributor
There was a problem hiding this comment.
style: When editing, messages after the edited one are correctly truncated
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/stores/copilot/store.ts
Line: 1609:1613
Comment:
**style:** When editing, messages after the edited one are correctly truncated
How can I resolve this? If you propose a fix, please make it concise.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Copilot UI impovements + bug fixes
Type of Change
Testing
Manual
Checklist